package cn.simple.run;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.http.HttpResponse;
import cn.simple.http.HttpRequest;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.*;
import com.intellij.execution.process.*;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

public class SimpleConfiguration extends RunConfigurationBase<SimpleRunConfigurationOptions> {

    public SimpleConfiguration(ConfigurationFactory configurationFactory, Project project) {
        super(project, configurationFactory, configurationFactory.getName());
    }

    @Override
    public @NotNull SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
        return null;
    }

    @Override
    public @Nullable RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) throws ExecutionException {
        return new CommandLineState(environment) {

            private ConsoleView console;
            @NotNull
            @Override
            protected ProcessHandler startProcess() throws ExecutionException {
                GeneralCommandLine commandLine = new GeneralCommandLine("cmd", "/c");
                OSProcessHandler processHandler = ProcessHandlerFactory.getInstance().createColoredProcessHandler(commandLine);
                ProcessTerminatedListener.attach(processHandler);
                processHandler.addProcessListener(new ProcessListener() {
                    @Override
                    public void processWillTerminate(@NotNull ProcessEvent event, boolean willBeDestroyed) {
                        console.clear();
                        HttpRequest request = getOptions().getHttpRequest();
                        try (HttpResponse response = request.execute()) {
                            Map<String, List<String>> responseHeaders = response.headers();
                            // 打印http url
                            printUrl(request.getMethod() + " " + request.getRealUrl() + " ", String.join(" ", responseHeaders.get(null)));
                            // 打印请求头
                            for (Map.Entry<String, String> entry : request.getRealHeaders().entrySet()) {
                                warning(entry.getKey() + ": " + entry.getValue());
                            }
                            info("");
                            // 打印请求体
                            if(request.getContent() != null && request.getContent().length > 0) {
                                debug(new String(request.getContent(), StandardCharsets.UTF_8));
                            }
                            // 打印响应头
                            for (Map.Entry<String, List<String>> entry : responseHeaders.entrySet()) {
                                if(entry.getKey() != null) {
                                    warning(entry.getKey() + ": " + String.join(" ", entry.getValue()));
                                }
                            }
                            info("");
                            debug(response.body());
                        } catch (Exception e) {
                            info(ExceptionUtil.getMessage(e));
                        }
                        ProcessListener.super.processWillTerminate(event, willBeDestroyed);
                    }
                });
                return processHandler;
            }

            private void printUrl(String url, String responseStatus) {
                console.print(url + " ", ConsoleViewContentType.LOG_DEBUG_OUTPUT);
                error(responseStatus);
            }

            private void warning(String message) {
                console.print(message + "\n", ConsoleViewContentType.LOG_WARNING_OUTPUT);
            }

            private void info(String message) {
                console.print(message + "\n", ConsoleViewContentType.LOG_INFO_OUTPUT);
            }

            private void error(String message) {
                console.print(message + "\n", ConsoleViewContentType.LOG_ERROR_OUTPUT);
            }

            private void debug(String message) {
                console.print(message + "\n", ConsoleViewContentType.LOG_DEBUG_OUTPUT);
            }

            @Override
            protected @Nullable ConsoleView createConsole(@NotNull Executor executor) throws ExecutionException {
                if(this.console == null) {
                    this.console = super.createConsole(executor);
                }
                return this.console;
            }
        };
    }

    public void setHttpRequest(HttpRequest httpRequest) {
        getOptions().setHttpRequest(httpRequest);
    }

    @Override
    protected @NotNull SimpleRunConfigurationOptions getOptions() {
        return (SimpleRunConfigurationOptions) super.getOptions();
    }
}
